from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from rest_framework import serializers

from audit.models import AuditManagement
from django.core.exceptions import ValidationError
from media.api.serializers import FileSerializer
from media.models import File

from .. import models

class InviteCodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.InviteCode
        exclude = []

class UserPermissionSerializer(serializers.ModelSerializer):
    link = serializers.SerializerMethodField()
    full_name = serializers.SerializerMethodField()

    user_group_type = serializers.SerializerMethodField()
    perm_can_manage_projects = serializers.SerializerMethodField()
    perm_can_manage_users = serializers.SerializerMethodField()
    perm_can_manage_resources = serializers.SerializerMethodField()
    
    class Meta:
        model = models.UserProfile
        fields = [
            'id', 'username', 'full_name', 'is_superuser', 'is_staff',
            'link', 'user_group_type', 'perm_can_manage_projects', 'perm_can_manage_users',
            'perm_can_manage_resources', 
        ]

    def get_full_name(self, user: models.UserProfile):
        return user.get_full_name()

    def get_perm_can_manage_projects(self, user: models.UserProfile):
        return user.has_perm("user.can_manage_projects")

    def get_perm_can_manage_users(self, user: models.UserProfile):
        return user.has_perm("user.can_manage_users")

    def get_perm_can_manage_resources(self, user: models.UserProfile):
        return user.has_perm("user.can_manage_resources")

    def get_user_group_type(self, user: models.UserProfile):
        # when creating superuser using Django management command,
        # the super is automatically added into 'external_personal' group
        # due to code in user/apps.py
        if user.is_superuser or user.groups.filter(name='internal_staff').exists():
            return 'internal_staff'
        return 'external_personal'

    def get_link(self, user: models.UserProfile):
        return reverse("admin:user_userprofile_change", args=[user.id])


class UserUpdateSerializer(serializers.ModelSerializer):
    # must have
    # Make `id` field writable (override the read-only default)
    # Make it required in the input data
    # Ensure it's properly validated as an integer
    id = serializers.IntegerField(required=True)
    
    class Meta:
        model = models.UserProfile
        fields = ['id', 'email', 'telephone', 'company', 'is_researcher', 'note']


class UserSerializer(serializers.ModelSerializer):
    link = serializers.SerializerMethodField()
    audit_status = serializers.SerializerMethodField()
    user_group_type = serializers.SerializerMethodField()
    full_name = serializers.SerializerMethodField()

    class Meta:
        model = models.UserProfile
        exclude = [
            "password", "first_name", "last_name", "third_app", "groups",
            "user_permissions"
        ]

    def get_full_name(self, user: models.UserProfile):
        return user.get_full_name()

    def get_user_group_type(self, user: models.UserProfile):
        if user.is_superuser:
            return 'internal_staff'
        # don't use `user.groups.filter(name='')` since it will create new query
        if any(group.name == 'internal_staff' for group in user.groups.all()):
            return 'internal_staff'
        return 'external_personal'

    def get_link(self, user: models.UserProfile):
        return reverse("admin:user_userprofile_change", args=[user.pk])

    def get_audit_status(self, user: models.UserProfile):
        ams = getattr(user, '_audit_management', [])
        return ams[0].status if ams else None
    

class ResearchersResumesSerializer(FileSerializer):
    researcher_username = serializers.SerializerMethodField()
    researcher_full_name = serializers.SerializerMethodField()
    
    class Meta(FileSerializer.Meta):
        # NOTE the `owner` field in File model means the uploader, not exactly
        # the same as the researcher
        exclude = FileSerializer.Meta.exclude + ['is_public']

    def get_researcher_username(self, file: File):
        return getattr(file, '_prefetched_researcher').user.username
    
    def get_researcher_full_name(self, file: File):
        return getattr(file, '_prefetched_researcher').user.full_name
